home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CUCD / Utilities / mpega_library / developer / demo / MPEGA_demo.c next >
Encoding:
C/C++ Source or Header  |  1997-11-02  |  8.2 KB  |  289 lines

  1. /*------------------------------------------------------------------------------
  2.  
  3.     File    :   MPEGA_demo.c
  4.  
  5.     Author  :   Stéphane TAVENARD
  6.  
  7.     $VER:   MPEGA_demo.c 1.0  (25/10/1997)
  8.  
  9.     (C) Copyright 1997-1997 Stéphane TAVENARD
  10.         All Rights Reserved
  11.  
  12.     #Rev|   Date   |                      Comment
  13.     ----|----------|--------------------------------------------------------
  14.     0   |25/10/1997| Initial revision                                     ST
  15.  
  16.     ------------------------------------------------------------------------
  17.  
  18.     Demo of how to use MPEGA library
  19.     Use of private bitstream access functions (access to ram buffer)
  20.  
  21. ------------------------------------------------------------------------------*/
  22.  
  23. #include <exec/exec.h>
  24. #include <clib/exec_protos.h>
  25. #include <pragmas/exec_pragmas.h>
  26. #include <dos.h>
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31.  
  32. #include <libraries/mpega.h>
  33. #include <clib/mpega_protos.h>
  34. #include <pragmas/mpega_pragmas.h>
  35.  
  36. static char *Version = "$VER:MPEGA_demo 1.0 (25.10.97) (C)1997 Stéphane TAVENARD";
  37.  
  38. struct Library *MPEGABase = NULL;
  39.  
  40. char *mpega_name = "mpega.library";
  41.  
  42. MPEGA_STREAM *mps = NULL;
  43.  
  44. // Ram buffer
  45. #define MPEGA_BUFFER_SIZE  (256*1024) // in bytes
  46.  
  47. BYTE   *mpega_buffer = NULL;
  48. ULONG  mpega_buffer_offset = 0;
  49. ULONG  mpega_buffer_size = 0;
  50.  
  51. static int break_cleanup( void )
  52. {
  53.    if( mps ) {
  54.       MPEGA_close( mps );
  55.       mps = NULL;
  56.    }
  57.    if( MPEGABase ) {
  58.       CloseLibrary( MPEGABase );
  59.       MPEGABase = NULL;
  60.    }
  61.    return 1;
  62. }
  63.  
  64. static void exit_cleanup( void )
  65. {
  66.    (void)break_cleanup();
  67. }
  68.  
  69. // Here start our own bitstream access routines
  70.  
  71. static ULONG __saveds __asm def_baccess( register __a0 struct Hook  *hook,
  72.                                          register __a2 APTR          handle,
  73.                                          register __a1 MPEGA_ACCESS *access ) {
  74. /*----------------------------------------------------------------------------
  75. */
  76.  
  77.    switch( access->func ) {
  78.  
  79.       case MPEGA_BSFUNC_OPEN:
  80.          // We don't really need stream_name
  81.          // buffer_size indicate the following read access size
  82.  
  83.          //printf( "bitstream open: '%s'\n", access->data.open.stream_name );
  84.  
  85.          // Some open errors...
  86.          if( !mpega_buffer ) return NULL;
  87.  
  88.          // initialize some variables
  89.          mpega_buffer_offset = 0;
  90.  
  91.          // We know total size, we can set it
  92.          access->data.open.stream_size = mpega_buffer_size;
  93.  
  94.          // Just return a dummy handle (not NULL)
  95.          return 1;
  96.  
  97.       case MPEGA_BSFUNC_CLOSE:
  98.          if( handle ) {
  99.             // Clean up
  100.             //printf( "bitstream close\n" );
  101.          }
  102.          break;
  103.       case MPEGA_BSFUNC_READ: {
  104.          LONG read_size;
  105.  
  106.          if( !handle ) return 0; // Check valid handle
  107.  
  108.          read_size = mpega_buffer_size - mpega_buffer_offset;
  109.          if( read_size > access->data.read.num_bytes ) read_size = access->data.read.num_bytes;
  110.  
  111.          if( read_size > 0 ) {
  112.             if( !access->data.read.buffer ) return 0;
  113.             // Fill buffer with our MPEG audio data
  114.             memcpy( access->data.read.buffer, &mpega_buffer[ mpega_buffer_offset ], read_size );
  115.             mpega_buffer_offset += read_size;
  116.          }
  117.          else {
  118.             read_size = 0; // End of stream
  119.          }
  120.          //printf( "bitstream read: requested %d bytes, read %d\n", access->data.read.num_bytes, read_size );
  121.  
  122.          return (ULONG)read_size;
  123.       }
  124.       case MPEGA_BSFUNC_SEEK:
  125.          if( !handle ) return 0;
  126.  
  127.          //printf( "bitstream seek: pos = %d\n", access->data.seek.abs_byte_seek_pos );
  128.          if( access->data.seek.abs_byte_seek_pos <= 0 ) mpega_buffer_offset = 0;
  129.          else if( access->data.seek.abs_byte_seek_pos >= mpega_buffer_size ) return 1;
  130.          else mpega_buffer_offset = access->data.seek.abs_byte_seek_pos;
  131.          return 0;
  132.    }
  133.    return 0;
  134. }
  135.  
  136. static struct Hook def_bsaccess_hook = {
  137.    { NULL, NULL }, def_baccess, NULL, NULL
  138. };
  139.  
  140. int output_pcm( WORD channels, WORD *pcm[ 2 ], LONG count, FILE *out_file )
  141. /*---------------------------------------------------------------------------
  142.    Ouput the current decoded PCM to a file
  143.    Return 0 if Ok
  144. */
  145. {
  146. #define PCM_BUFFER_SIZE (MPEGA_MAX_CHANNELS*MPEGA_PCM_SIZE)
  147.    static WORD *pcm_buffer = NULL;
  148.    if( !out_file ) return -1;
  149.  
  150.    if( !pcm_buffer ) {
  151.       pcm_buffer = (WORD *)malloc( PCM_BUFFER_SIZE * sizeof(WORD) );
  152.       if( !pcm_buffer ) return -1;
  153.    }
  154.    if( channels == 2 ) {
  155.       register WORD *pcm0, *pcm1, *pcmLR;
  156.       register LONG i;
  157.  
  158.       pcm0 = pcm[ 0 ];
  159.       pcm1 = pcm[ 1 ];
  160.       pcmLR = pcm_buffer;
  161.       i = count;
  162.       while( i-- ) {
  163.          *pcmLR++ = *pcm0++;
  164.          *pcmLR++ = *pcm1++;
  165.       }
  166.       fwrite( pcm_buffer, 4, count, out_file );
  167.    }
  168.    else {
  169.       fwrite( pcm[ 0 ], 2, count, out_file );
  170.    }
  171.  
  172.    return 0;
  173.  
  174. } /* output_pcm */
  175.  
  176. int main( int argc, char **argv )
  177. {
  178.    char *in_filename;
  179.    FILE *in_file;
  180.    int frame = 0;
  181.    char *out_filename = NULL;
  182.    FILE *out_file = NULL;
  183.    WORD i;
  184.    LONG pcm_count;
  185.    WORD *pcm[ MPEGA_MAX_CHANNELS ];
  186.  
  187.    static const char *layer_name[] = { "?", "I", "II", "III" };
  188.    static const char *mode_name[] = { "stereo", "j-stereo", "dual", "mono" };
  189.  
  190.    MPEGA_CTRL mpa_ctrl = {
  191.       NULL,    // Bitstream access is default file I/O
  192.       // Layers I & II settings (mono, stereo)
  193.       { FALSE, { 1, 2, 48000 }, { 1, 2, 48000 } },
  194.       // Layer III settings (mono, stereo)
  195.       { FALSE, { 1, 2, 48000 }, { 1, 2, 48000 } },
  196.       0,           // Don't check mpeg validity at start (needed for mux stream)
  197.       2048         // Stream Buffer size
  198.    };
  199.  
  200.    onbreak( break_cleanup );
  201.    atexit( exit_cleanup );
  202.  
  203.    if( argc <= 1 ) {
  204.       fprintf( stderr, "%s\n", &Version[ 5 ] );
  205.       fprintf( stderr, "Usage %s <input mpeg audio file> [<output pcm file>]\n", argv[ 0 ] );
  206.       fprintf( stderr, "This is a demo of how to use mpega.library\n" );
  207.       fprintf( stderr, "This also show how to use custom bitstream access\n" );
  208.       exit( 0 );
  209.    }
  210.  
  211.    MPEGABase = OpenLibrary( mpega_name, 0L );
  212.    if( !MPEGABase ) {
  213.       printf( "Unable to open '%s'\n", mpega_name );
  214.       exit( 0 );
  215.    }
  216.  
  217.    in_filename = argv[ 1 ];
  218.    if( argc > 2 ) out_filename = argv[ 2 ];
  219.  
  220.    mpega_buffer = (BYTE *)malloc( MPEGA_BUFFER_SIZE );
  221.    if( !mpega_buffer ) {
  222.       fprintf( stderr, "Can't allocate MPEG buffer\n" );
  223.       exit( 0 );
  224.    }
  225.  
  226.    for( i=0; i<MPEGA_MAX_CHANNELS; i++ ) {
  227.       pcm[ i ] = malloc( MPEGA_PCM_SIZE * sizeof( WORD ) );
  228.       if( !pcm[ i ] ) {
  229.          fprintf( stderr, "Can't allocate PCM buffers\n" );
  230.          exit( 0 );
  231.       }
  232.    }
  233.  
  234.    // Open the output file
  235.    if( out_filename ) {
  236.       out_file = fopen( out_filename, "wb" );
  237.       if( !out_file ) {
  238.          fprintf( stderr, "Can't create output file '%s'\n", out_filename );
  239.          exit( 0 );
  240.       }
  241.    }
  242.  
  243.    // Load the stream into a ram buffer
  244.    in_file = fopen( in_filename, "rb" );
  245.    if( !in_file ) {
  246.       fprintf( stderr, "Unable to open file '%s'\n", in_filename );
  247.       exit( 0 );
  248.    }
  249.    mpega_buffer_size = fread( mpega_buffer, 1, MPEGA_BUFFER_SIZE, in_file );
  250.    fclose( in_file );
  251.    printf( "Read %d bytes from file '%s'\n", mpega_buffer_size, in_filename );
  252.  
  253.    // Set our bitstream access routines and open the stream
  254.    mpa_ctrl.bs_access = &def_bsaccess_hook;
  255.  
  256.    mps = MPEGA_open( in_filename, &mpa_ctrl );
  257.    if( !mps ) {
  258.       printf( "Unable to find MPEG Audio stream in file '%s'\n", in_filename );
  259.       exit( 0 );
  260.    }
  261.  
  262.    printf( "\n" );
  263.    printf( "MPEG norm %d Layer %s\n", mps->norm, layer_name[ mps->layer ] );
  264.    printf( "Bitrate: %d kbps\n", mps->bitrate );
  265.    printf( "Frequency: %d Hz\n", mps->frequency );
  266.    printf( "Mode: %d (%s)\n", mps->mode, mode_name[ mps->mode ] );
  267.    printf( "Stream duration: %ld ms\n", mps->ms_duration );
  268.    printf( "\n" );
  269.    printf( "Output decoding parameters\n" );
  270.    printf( "Channels: %d\n", mps->dec_channels );
  271.    printf( "Quality: %d\n", mps->dec_quality );
  272.    printf( "Frequency: %d Hz\n", mps->dec_frequency );
  273.    printf( "\n" );
  274.  
  275.    while( (pcm_count = MPEGA_decode_frame( mps, pcm )) >= 0 ) {
  276.       if( out_file ) output_pcm( mps->dec_channels, pcm, pcm_count, out_file );
  277.       frame++;
  278.       fprintf( stderr, "{%04d}\r", frame ); fflush( stderr );
  279.    }
  280.    fprintf( stderr, "\n" );
  281.  
  282.    MPEGA_close( mps );
  283.    mps = NULL;
  284.    CloseLibrary( MPEGABase );
  285.    MPEGABase = NULL;
  286.  
  287. }
  288.  
  289.